﻿//===================================================================================
// Copyright (c) Ryan Garrett.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===================================================================================
using System;

namespace Caffeine.Core
{
    /// <summary>
    /// Provides extension methods for the Caffeine.Core.ModelPropertyBehavior enumeration
    /// </summary>
    public static class ModelPropertyBaseExtensions
    {
        #region Public

        /// <summary>
        /// Checks whether or not this property observes the ModelPropertyBehavior.SetsIsDirty behavior
        /// </summary>
        /// <param name="modelProperty">Property to check</param>
        /// <returns>True if the behavior is observed by the property, otherwise false</returns>
        public static Boolean CheckSetsIsDirty(this ModelPropertyBase modelProperty)
        {
            return modelProperty.Behavior != null && CheckIsValid(modelProperty.Behavior.Value, ModelPropertyBehaviors.SetsIsDirty);
        }

        /// <summary>
        /// Checks whether or not this property observes the ModelPropertyBehavior.SetsParentIsDirty behavior
        /// </summary>
        /// <param name="modelProperty">Property to check</param>
        /// <returns>True if the behavior is observed by the property, otherwise false</returns>
        public static Boolean CheckSetsParentIsDirty(this ModelPropertyBase modelProperty)
        {
            return modelProperty.Behavior != null && CheckIsValid(modelProperty.Behavior.Value, ModelPropertyBehaviors.SetsParentIsDirty);
        }

        /// <summary>
        /// Checks whether or not this property observes the ModelPropertyBehavior.SetsIsInvalid behavior
        /// </summary>
        /// <param name="modelProperty">Property to check</param>
        /// <returns>True if the behavior is observed by the property, otherwise false</returns>
        public static Boolean CheckSetsIsInvalid(this ModelPropertyBase modelProperty)
        {
            return modelProperty.Behavior != null && CheckIsValid(modelProperty.Behavior.Value, ModelPropertyBehaviors.SetsIsInvalid);
        }

        /// <summary>
        /// Checks whether or not this property observes the ModelPropertyBehavior.SetsParentIsInvalid behavior
        /// </summary>
        /// <param name="modelProperty">Property to check</param>
        /// <returns>True if the behavior is observed by the property, otherwise false</returns>
        public static Boolean CheckSetsParentIsInvalid(this ModelPropertyBase modelProperty)
        {
            return modelProperty.Behavior != null && CheckIsValid(modelProperty.Behavior.Value, ModelPropertyBehaviors.SetsParentIsInvalid);
        }

        /// <summary>
        /// Checks whether or not this property observes the ModelPropertyBehavior.IsResettable behavior
        /// </summary>
        /// <param name="modelProperty">Property to check</param>
        /// <returns>True if the behavior is observed by the property, otherwise false</returns>
        public static Boolean CheckIsResettable(this ModelPropertyBase modelProperty)
        {
            return modelProperty.Behavior != null && CheckIsValid(modelProperty.Behavior.Value, ModelPropertyBehaviors.IsResettable);
        }

        /// <summary>
        /// Checks whether or not this property observes the ModelPropertyBehavior.SupportsPropertyChangeCounting behavior
        /// </summary>
        /// <param name="modelProperty">Property to check</param>
        /// <returns>True if the behavior is observed by the property, otherwise false</returns>
        public static Boolean CheckSupportsPropertyChangeCounting(this ModelPropertyBase modelProperty)
        {
            return modelProperty.Behavior != null && CheckIsValid(modelProperty.Behavior.Value, ModelPropertyBehaviors.SupportsPropertyChangeCounting);
        }

        /// <summary>
        /// Checks whether or not this property observes the ModelPropertyBehavior.IsWrapped behavior
        /// </summary>
        /// <param name="modelProperty">Property to check</param>
        /// <returns>True if the behavior is observed by the property, otherwise false</returns>
        public static Boolean CheckIsWrapped(this ModelPropertyBase modelProperty)
        {
            return modelProperty.IsWrapped;
        }

        /// <summary>
        /// Remove a behavior
        /// </summary>
        /// <param name="behavior">Current behavior</param>
        /// <param name="behaviorToRemove">Behavior to remove</param>
        /// <returns>Property behavior</returns>
        public static ModelPropertyBehaviors RemoveBehavior(this ModelPropertyBehaviors behavior, ModelPropertyBehaviors behaviorToRemove)
        {
            return behavior ^ behaviorToRemove;
        }

        /// <summary>
        /// Add a behavior
        /// </summary>
        /// <param name="behavior">Current behavior</param>
        /// <param name="behaviorToAdd">Behavior to add</param>
        /// <returns>Property behavior</returns>
        public static ModelPropertyBehaviors AddBehavior(this ModelPropertyBehaviors behavior, ModelPropertyBehaviors behaviorToAdd)
        {
            return behavior | behaviorToAdd;
        }

        #endregion

        #region Internal

        internal static Boolean CheckIsValid(ModelPropertyBehaviors containingBehavior, ModelPropertyBehaviors behaviorToCheck)
        {
            return (containingBehavior & behaviorToCheck) == behaviorToCheck;
        }

        #endregion
    }
}
